#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdint.h>

/*
Парные методы (get/release alloc/free init/deinit) должны быть вызываны внутри одного и того же треда. 
А также логично, что каждый тред, который использует память должен для себя сам вызвать get.
В этом случае аллокатор гарантирует, что его функции возвращают корректные данные.
Иначе имеем undefined behavior.
*/

int ma_init(uint64_t mem, uint64_t swap, const char* swap_path);
/*
ma_init() инициализирует алокатор памяти со следующими параметрами:
максимум использованной оперативной памяти которая будет задействованна устанавливается в размере mem байт
максимальный размер файла подкачки равен swap байтам
файл подкачки расположен по относительному или абсолютному адресу записаному в swap_path

Возвращаемое значение: 1 - успешно выполнена инициализация.
0 - вовремя инициализации возникли ошибки, код ошибки записан в errno

Коды ошибок для errno
EALREADY - повторный вызов ma_init

ENOMEM - невозможно выделить место под кучу размеров mem
EACCES - нет прав доступа к файлу swap_path
EFAULT - все остальные ошибки связанные с файлом подкачки(возможность создания файла заданного размера не проверяется на этом этапе)

EBADR - mem>swap

*/



void ma_deinit();
/*
ma_deinit завершает работу аллокатора памяти, освобождая всю занятую память, и удаляя файл подкачки.
*/



uint64_t ma_alloc(uint64_t sz);
/*
ma_alloc выдаёт внутренний идентификатор участка памяти длиной sz байт. Корректная работа гарантируется при 2^6 < sz < 2^26.
Валидные индентификаторы от 1 до максимального значения uint64_t.
Присвоение индентификаторов происходит таким образом чтобы каждый вновь выделенный идентификатор не совпал ни с одним ранее выделеным.
При этом EMLINK гарантированно не будет возвращен, если было произведено не более, чем sz - 1 вызовов ma_alloc().
В случае ошибки аллокации возвращается 0, а код ошибки записывается в errno

Коды ошибок
ENOMEM - в куче недостаточно памяти для выделения участка размером sz (swap - уже_выделенная_память < sz)
E2BIG - запрашиваемый участок памяти невозможно будет уместить в оперативной памяти (mem < sz)
EMLINK - закончились свободные идентификаторы

ECANCELED - вызов функции до инициализации аллокатора
*/ 


int ma_free(uint64_t id);
/*
Освобождает память занимаемую участком с внутренним идентификатором id.

Возвращаемое значение:
1 - успешно выполнено.
0 - в качестве аргумента использован не валидный идентификатор. В этом случае errno присваивается код ошибки:

EINVAL - невалидное значение идентификатора (н-р, 0)
EFAULT - память с таким идентификатором ещё не выделена, или уже освобождена
EBUSY - память ещё не освобождена
ECANCELED - вызов функции до инициализации аллокатора
*/



void* ma_get(uint64_t id);
/*
ma_get() возвращает указатель на участок памяти с внутренним идентификатором id.
До тех пор пока в отношении того же идентификатора не будет вызвана "парная" функция ma_release() или ma_deinit() гарантируется валидность этого указателя(SAFEMODE).
Корректная работа гарантируется для вызова ma_get не более 2^32 раз для одного и того же id.
В случае ошибки возвращается NULL, а код ошибки записывается в errno
Коды ошибок
EINVAL - невалидное значение идентификатора (н-р, 0)
EFAULT - память с таким идентификатором ещё не выделена, или уже освобождена
ENOMEM - недостаточно места в оперативной памяти
ENOBUFS - память слишком фрагментирована

EBADF - ошибка файла подкачки
EFBIG - запрашиваемый размер файла подкачки слишком большой

ECANCELED - вызов функции до инициализации аллокатора

to be continued...
*/


int ma_release(uint64_t id);
/*
ma_release() указывает на то что участок памяти с идентификатором id больше не будет использован и в случае необходимости его можно переместить в файл подкачки.
Если по этому id ранее был выдан указатель функцией get(id), то изменение памяти по этому указателю может привести к потерям внесённых изменений, либо порче кучи.

Возвращаемое значение:
1 - успешно выполнено.
0 - в качестве аргумента использован не валидный идентификатор. В этом случае errno присваивается код ошибки:

EINVAL - невалидное значение идентификатора (н-р, 0)
EFAULT - память с таким идентификатором ещё не выделена, или уже освобождена(с помощью ma_free() или ma_release()

ECANCELED - вызов функции до инициализации аллокатора
*/
